import { documentTitle } from '@/router/documentTitle'
import Nprogress from 'nprogress'
import 'nprogress/nprogress.css'
import { useAuth } from '@/stores/auth'
import { notFoundRouter } from './modules/staticRoutes'
import { useSettingsStore } from '@/stores/settings'

const whiteList = ['/login', '/register']

/**
 * 匹配组件
 * @param {*} asyncRouterMap
 * @param {*} vueView
 */
function filterAsyncRouter(asyncRouterMap, vueView) {
  return asyncRouterMap.filter((route) => {
    // 如果当前循环次route.component
    route.component = vueView[`/src/views${route.component}.vue`] // 则进行vue文件匹配

    route.meta = typeof route.meta === 'string' ? JSON.parse(route.meta) : route.meta
    if (route.children && route.children.length) {
      route.children = filterAsyncRouter(route.children, vueView)
    }
    return true
  })
}

/**
 * 递归添加动态路由
 */
function addDynamicRoutes(routes, router) {
  routes.forEach((route) => {
    if (route.children && route.children.length) {
      router.addRoute('layout', route) // 从此处添加动态路由,保证添加的路由和树状菜单一致

      addDynamicRoutes(route.children, router)
    }
  })
}

const { getAllViewsVueFiles } = getViewsFiles() // 获取所有views文件夹下的vue文件
// 动态添加路由
const vueView = getAllViewsVueFiles() // 获取所有views文件夹下的vue文件

export const guard = (router) => {
  // 导航前置守卫
  router.beforeEach(async (to, from, next) => {
    Nprogress.start({
      parent: '#app',
      speed: 500
    })
    documentTitle(to.meta.title)

    const authStore = useAuth()
    const settings = useSettingsStore()
    // console.log(to)
    if (to.redirectedFrom && to.redirectedFrom.meta.PARENT_ID == 0) {
      settings.activeMenu = to.redirectedFrom.path
    } else {
      settings.activeMenu = to.path
    }

    // 白名单处理
    if (whiteList.includes(to.path)) return next()
    // 如果访问的是登录页,并且已经登录,则跳转到首页或来源页
    if (to.path == '/login') {
      if (localStorage.getItem('token')) return next(from.fullPath)
      authStore.menu = []
      router.resetRouter()
      return next()
    }
    // 判断是否在每次的路由跳转时,是否有token,如果没有则跳转到登录页
    if (!localStorage.getItem('token')) return next('/login')

    // 从接口来的动态菜单
    try {
      if (!authStore.menu.length) {
        const apiMenu = await authStore.getSlideMenuAction() // 发起请求,获取接口中的树状左侧菜单
        authStore.setMenus(apiMenu)
        if (!apiMenu.length) return next()

        // 无限递归,将接口中的树状菜单,转换成路由
        const routes = filterAsyncRouter(apiMenu, vueView)
        // 递归添加动态路由
        await addDynamicRoutes(routes, router)

        // 添加404路由
        await router.addRoute(notFoundRouter)
        authStore.setMenus(apiMenu) // 存储 pinia 中的 menu,必须要在添加动态路由之后,否则会报错

        return next({ ...to, replace: true }) // return 中断下方 展开要去的路由对象,并且替换当前路由,replace: true 代表替换当前路由,会再次触发路由守卫,确保addRoute添加的路由生效
      }
    } catch (error) {
      console.error(error)
    }

    // 正常访问的路由,直接放行
    next()
  })

  // 导航后置守卫
  // eslint-disable-next-line
  router.afterEach((to, from) => {
    // console.log('导航后置守卫', from, to)
    Nprogress.done()
  })
}
